/*****************************
 *@file: GameScene
 *@author: 陈吕唐
 *@desc: 游戏场景逻辑
 *@date: 2024-03-19	18:33
 *****************************/
import { _decorator, AssetManager, Button, Component, game, Label, log, math, Node, ProgressBar, v3 } from 'cc';
import { DEBUG } from 'cc/env';
import CharacterManageSingle from '../character/CharacteManageSingle';
import MonsterDTO from '../pojo/dto/MonsterDTO';
import { BaseCharacter } from './BaseCharacter';
import IBaseAttribute from './character/IBaseAttribute';
import { CharacterEvent } from './CharacterEvent';
import GameSingle from './GameSingle';
import { BaseHeroCharacter } from './hero/BaseHeroCharacter';
import IHeroAttribute from './hero/IHeroAttribute';
import IGameScene from './IGameScene';
import LevelPO from './level/LevelPO';
import MonsterWave from './level/MonsterWave';
import LevelManageSingle from './LevelManageSingle';
import { BaseMonsterCharacter } from './monster/BaseMonsterCharacter';
import IMonsterAttribute from './monster/IMonsterAttribute';
const { ccclass, property } = _decorator;

@ccclass('GameScene')
export class GameScene extends Component implements IGameScene {
    /****************************************************************************************************************
     *Readonly 常量
     ****************************************************************************************************************/
    /****************************************************************************************************************
     *Property 定义变量
     ****************************************************************************************************************/
    /**
     * 游戏是否进行中
     */
    protected gameIng: boolean = false;


    /**
     * 当前游戏时间
     */
    private _passTime: number = 0;


    /**
     * 总波次数目
     */
    private maxWave: number = 0;

    /**
     * 当前波次数目
     */
    private _nowWave: number = 0;


    /**
     * 当前关卡数据
     */
    private level: LevelPO = undefined!;
    /***************************************************************
     *PropertyUI 引用的控件
     ***************************************************************/
    @property({ group: { name: 'Game', id: '1' }, type: Node, tooltip: `怪物容器组件` })
    private monsterLayout: Node = undefined!;

    @property({ group: { name: 'Game', id: '1' }, type: Node, tooltip: `英雄容器组件` })
    private heroLayout: Node = undefined!;

    @property({ group: { name: 'Game', id: '1' }, type: BaseCharacter, tooltip: `建筑物组件` })
    public build: BaseCharacter = undefined!;

    @property({ group: { name: 'Game', id: '1' }, type: ProgressBar, tooltip: `关卡资源加载进度条` })
    private progress: ProgressBar = undefined!;


    @property({ group: { name: 'Game', id: '1' }, type: Label, tooltip: `当前游戏经过的时间文本组件` })
    private timeLabel: Label = undefined!;

    @property({ group: { name: 'Game', id: '1' }, type: Label, tooltip: `当前游戏波次文本组件` })
    private waveLabel: Label = undefined!;
    /**********************************************
     * 游戏功能UI
     **********************************************/
    @property({ group: { name: 'Game', id: '1' }, type: Button, tooltip: `暂停游戏按钮组件` })
    private pauseButton: Button = undefined!;

    @property({ group: { name: 'Game', id: '1' }, type: Button, tooltip: `恢复游戏按钮组件` })
    private resumeButton: Button = undefined!;
    /****************************************************************************************************************
     * Lifecycle 生命周期相关方法
     ****************************************************************************************************************/
    protected onLoad(): void {
        this.monsterLayout.on(Node.EventType.CHILD_REMOVED, this.gameJudge, this);
        this.build.node.on(CharacterEvent.GAME_LOSE, this.gameLose, this);
        this.pauseButton.node.on(Button.EventType.CLICK, this.pauseGame, this);
        this.resumeButton.node.on(Button.EventType.CLICK, this.resumeGame, this);

        this.loadHero();
    }

    protected lateUpdate(dt: number): void {
        if (!this.gameIng) {
            return;
        }
        this.passTime += dt;
    }
    /****************************************************************************************************************
     * Public 公有方法
     ****************************************************************************************************************/
    /****************************************************************************************************************
     * private 私有方法
     ****************************************************************************************************************/
    /**
     * 根据关卡数据加载/初始化关卡
     */
    protected loadLevel(level: LevelPO) {
        this.level = level;
        /**
         * 加载关卡所需资源
         */
        let promise = GameSingle.single.loadAssets(level, (finished: number, total: number, item: AssetManager.RequestItem) => {
            this.progress.progress = finished / total;
        });
        return promise;
    }

    protected loadComplete() {
        this.progress.node.active = false;
    }

    /**
     * 添加一波怪物到场上
     * @param wave 怪物波次数据
     */
    protected addMonster(wave: MonsterWave) {

        let values: MonsterDTO[] = [];

        for (let i = 0; i < wave.number; i++) {
            let v: MonsterDTO = { id: wave.monsterId, lv: wave.lv };
            values.push(v);
        }


        for (let i = 0; i < values.length; i++) {
            const element = values[i];
            let node = GameSingle.single.getMonster(element.id);
            let attribute: IMonsterAttribute = LevelManageSingle.single.calMonsterAttribute(element);
            let monster = node.getComponent(BaseMonsterCharacter);
            monster.init(attribute);

            let y = math.random() * 800 - 400;
            let pos = v3(0, y, 0);
            node.position = pos;

            this.monsterLayout.addChild(node);
            monster.startGame();
        }
    }


    /**
     * 加载/初始化英雄
     */
    protected loadHero(values: number[] = []) {
        let promise = GameSingle.single.loadHeroAssets(values);
        return promise;
    }

    /**
     * 添加英雄到场上
     * @param values 出战英雄ID
     */
    protected addHero(values: number[]) {
        for (let i = 0; i < values.length; i++) {
            const element = values[i];
            let node = GameSingle.single.getHero(element);
            let attribute: IHeroAttribute = CharacterManageSingle.single.getEntityById(element);
            let hero = node.getComponent(BaseHeroCharacter);
            this.heroLayout.addChild(node);
            hero.init(attribute);
            hero.startGame();
        }

    }

    /**
     * 开始游戏
     */
    protected startGame() {
        GameSingle.single.scene = this;
        this.gameIng = true;
        this.passTime = 0;

        let value: IBaseAttribute = { hp: 1000, atk: 30, def: 0, spd: 0 };
        this.build.init(value);
        this.build.startGame();

        let maxTime: number = 0;
        this.nowWave = 0;
        /**
         * 加载怪物波次
         */
        let waves: MonsterWave[] = this.level.waves;
        for (let i = 0; i < waves.length; i++) {
            const wave = waves[i];
            if (wave.time > maxTime) {
                maxTime = wave.time;
            }

            this.scheduleOnce(() => {
                this.addMonster(wave);
                this.nowWave++;
            }, wave.time)
        }

        this.maxWave = waves.length;
    }

    /**
     * 暂停游戏
     */
    protected pauseGame() {
        game.pause();
    }

    /**
     * 更新当前游戏经过的时间
     * @param value 
     */
    private updateGameTime(value: number) {
        if (this.timeLabel) {
            this.timeLabel.string = `${value.toFixed(0)}秒`;
        }
    }


    private updateGameWave(value: number) {
        if (this.waveLabel) {
            this.waveLabel.string = `${value}/${this.maxWave}`;
        }
    }

    /**
     * 从暂停中恢复游戏
     */
    protected resumeGame() {
        game.resume();
    }

    /**
     * 结束游戏
     */
    private endGame() {
        this.gameIng = false;
    }
    /**
     * 游戏胜利判断
     */
    private gameJudge() {
        if (!this.gameIng) {
            return;
        }

        if (this.nowWave < this.maxWave) {
            return;
        }

        if (this.monsterLayout.children.length <= 0) {
            this.gameWin();
            return;
        }
    }
    /**
     * 游戏胜利
     */
    private gameWin() {
        this.endGame();
        if (DEBUG) {
            this.timeLabel.string = `游戏胜利`;
            log(`游戏胜利`);
        }
    }

    /**
     * 游戏失败
     */
    private gameLose() {
        this.endGame();
        if (DEBUG) {
            this.timeLabel.string = `游戏失败`;
            log(`游戏失败`);
        }
    }
    /****************************************************************************************************************
     * Property Get && Set 属性的 get && set 函数
     ****************************************************************************************************************/
    public get heros(): BaseCharacter[] {
        if (!this.gameIng) {
            return [];
        }
        return [];
    }

    public get monsters(): BaseCharacter[] {
        if (!this.gameIng) {
            return [];
        }
        return [];
    }

    /**
     * 当前经过的游戏时间
     */
    private get passTime(): number {
        return this._passTime;
    }

    private set passTime(value: number) {
        this._passTime = value;
        this.updateGameTime(value);
    }

    public get nowWave(): number {
        return this._nowWave;
    }
    public set nowWave(value: number) {
        this._nowWave = value;
        this.updateGameWave(value);
    }
}


